package com.knowno.service.impl;

import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.knowno.config.AliPayConfig;
import com.knowno.dao.TOrderDao;
import com.knowno.dto.AliPay;
import com.knowno.entity.TOrder;
import com.knowno.service.TOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * DATE = 2023/7/17 20:31
 */
@Service
@Slf4j
public class OrdersServiceImpl implements TOrderService {

    //沙箱中网关的地址(支付宝网关地址)
    private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
    @Resource
    private TOrderDao tOrderDao;


    @Resource
    private AliPayConfig aliPayConfig;

    public OrdersServiceImpl() {
        log.info("Alipay service start......");
    }

    /**
     * 支付宝回传页面方法
     *
     * @param aliPay
     * @param response
     */
    @Override
    public void pay(AliPay aliPay, HttpServletResponse response) throws IOException {

        // 1. 创建Client，通用SDK提供的Client，负责调用支付宝的API
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(), "json","UTF-8", aliPayConfig.getAlipayPublicKey(),"RSA2");
        // 2. 创建 Request并设置Request参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        //设置回调URL地址
        request.setNotifyUrl(aliPayConfig.getNotifyUrl());
        //设置返回的URL地址
        request.setReturnUrl(aliPayConfig.getReturnUrl());
        log.info(" NotifyUrl {}",aliPayConfig.getNotifyUrl());
        JSONObject bizContent = new JSONObject();
        // 自己生成的订单编号
        bizContent.set("out_trade_no", aliPay.getTraceNo());
        // 订单的总金额
        bizContent.set("total_amount", aliPay.getTotalAmount());
        // 支付的名称
        bizContent.set("subject", aliPay.getSubject());
        // 固定配置
        bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY");
        request.setBizContent(bizContent.toString());

        //订单信息插入表中[自定义业务逻辑] ->insert
        TOrder tOrder = new TOrder();
        BeanUtils.copyProperties(aliPay, tOrder);
        tOrder.setOrderNo(aliPay.getTraceNo());
        tOrder.setTotalPrice(Double.parseDouble(aliPay.getTotalAmount()));
        tOrder.setName(aliPay.getSubject());
        tOrder.setCreateTime(new Date());
        tOrder.setPayPrice(Double.parseDouble(aliPay.getTotalAmount()));
        tOrder.setDiscount(0.0);
        tOrder.setTransportPrice(0.0);
        tOrder.setState(0);
        log.info(" tOrder {}",tOrder);
        this.tOrderDao.insert(tOrder);


        // 执行请求，拿到响应的结果，返回给浏览器
        String form = "";
        try {
            // 调用SDK生成表单
            form = alipayClient.pageExecute(request).getBody();
            log.info(form);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        response.setContentType("text/html;charset=utf-8");
        // 直接将完整的表单html输出到页面
        response.getWriter().write(form);
        response.getWriter().flush();
        response.getWriter().close();
    }

    /**
     * 根据回调接口传来的参数修改订单信息
     *
     * @param request
     */
    @Override
    public int payNotify(HttpServletRequest request) throws AlipayApiException {
        log.info("支付回调请求处理");
        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
                System.out.println(name + " = " + request.getParameter(name));
            }

            String outTradeNo = params.get("out_trade_no");
            String gmtPayment = params.get("gmt_payment");
            String alipayTradeNo = params.get("trade_no");

            String sign = params.get("sign");
            log.info("sign {}",sign);
            String content = AlipaySignature.getSignCheckContentV1(params);
            log.info("content {}",content);
            // 验证签名
            boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, aliPayConfig.getAlipayPublicKey(), "UTF-8");
           log.info("checkSignature {}",checkSignature);
            // 支付宝验签
            if (checkSignature) {
                // 验签通过
                log.info("交易名称:{} ", params.get("subject"));
                log.info("交易状态:{} " , params.get("trade_status"));
                log.info("支付宝交易凭证号:{} " , params.get("trade_no"));
                log.info("商户订单号: {}" , params.get("out_trade_no"));
                log.info("交易金额: {}" , params.get("total_amount"));
                log.info("买家在支付宝唯一id:{} " , params.get("buyer_id"));
                log.info("买家付款时间: {}" , params.get("gmt_payment"));
                log.info("买家付款金额: {}" , params.get("buyer_pay_amount"));

                log.info("修改订单信息实体类参数：{}",tOrderDao);
                // 更新订单未已支付
                return   tOrderDao.updateState(outTradeNo, 1, gmtPayment);

            }
        }
        //修改失败，未支付
        return 0;

    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public TOrder queryById(Integer id) {
        return this.tOrderDao.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param tOrder 筛选条件
     * @param pageRequest      分页对象
     * @return 查询结果
     */
    @Override
    public Page<TOrder> queryByPage(TOrder tOrder, PageRequest pageRequest) {
        long total = this.tOrderDao.count(tOrder);
        return new PageImpl<>(this.tOrderDao.queryAllByLimit(tOrder, pageRequest), pageRequest, total);
    }

    /**
     * 新增数据
     *
     * @param tOrder 实例对象
     * @return 实例对象
     */
    @Override
    public TOrder insert(TOrder tOrder) {
        this.tOrderDao.insert(tOrder);
        return tOrder;
    }

    /**
     * 修改数据
     *
     * @param tOrder 实例对象
     * @return 实例对象
     */
    @Override
    public TOrder update(TOrder tOrder) {
        this.tOrderDao.update(tOrder);
        return this.queryById(tOrder.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.tOrderDao.deleteById(id) > 0;
    }

    @Override
    public int updateState(String tradeNo, int state, String payTime) {
        return tOrderDao.updateState(tradeNo,state,payTime);
    }


}
